package com.example.lab.config;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.example.lab.entity.User;
import com.example.lab.filter.JwtAuthenticationFilter;
import com.example.lab.result.Result;
import com.example.lab.result.ResultCode;
import com.example.lab.service.impl.UserServiceImpl;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

/**
 *@Author: 布莱恩
 *@Date: 2025/6/16 23:48
 *@Description:
 **/
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig {

    private final JwtAuthenticationFilter jwtAuthenticationFilter;

    /**
     * 配置Security过滤链
     *
     * 该方法用于配置Spring Security的过滤链，以定义如何处理 incoming requests
     * 它配置了csrf保护、会话管理、请求授权规则、自定义过滤器以及异常处理
     *
     * @param http HttpSecurity实例，用于配置Web安全
     * @return SecurityFilterChain对象，代表配置好的安全过滤链
     * @throws Exception 配置过程中可能抛出的异常
     */
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                // 禁用csrf保护，因为我们的应用可能不需要它
                .csrf(AbstractHttpConfigurer::disable)
                // 配置会话管理，设置会话创建策略为无状态，因为我们使用的是JWT认证
                .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
                // 配置请求授权规则
                .authorizeHttpRequests(auth -> auth
                        // 允许所有认证相关的请求无需认证
                        .requestMatchers("/api/auth/login", "/api/auth/current-user").permitAll()
                        .requestMatchers("/error").permitAll()
                        // 用户管理权限
                        .requestMatchers(HttpMethod.GET, "/api/users").hasAuthority("user:manage")
                        .requestMatchers(HttpMethod.GET, "/api/users/{id}").hasAuthority("user:manage")
                        .requestMatchers(HttpMethod.POST, "/api/users").hasAuthority("user:create")
                        .requestMatchers(HttpMethod.PUT, "/api/users/{id}").hasAuthority("user:edit")
                        .requestMatchers(HttpMethod.DELETE, "/api/users/{id}").hasAuthority("user:delete")
                        .requestMatchers("/api/users/roles").hasAuthority("user:manage")
                        .requestMatchers(HttpMethod.POST, "/api/users/{userId}/roles").hasAuthority("user:manage")
                        // 其他所有请求都需要认证
                        .anyRequest().authenticated()
                )
                // 在UsernamePasswordAuthenticationFilter之前添加JWT认证过滤器
                .addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
                // 配置异常处理
                .exceptionHandling(exception -> exception
                        // 配置认证入口点，处理未认证的请求
                        .authenticationEntryPoint(((request, response, authException) -> {
                            response.setContentType(MediaType.APPLICATION_JSON_VALUE);
                            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
                            response.getWriter().write(new ObjectMapper().writeValueAsString(
                                    Result.fail(ResultCode.UNAUTHORIZED.getCode(), "未认证，请先登录")
                            ));
                        }))
                        // 配置访问拒绝处理器，处理权限不足的情况
                        .accessDeniedHandler((request, response, accessDeniedException) -> {
                            response.setContentType(MediaType.APPLICATION_JSON_VALUE);
                            response.setStatus(HttpServletResponse.SC_FORBIDDEN);
                            response.getWriter().write(new ObjectMapper().writeValueAsString(
                                    Result.fail(ResultCode.FORBIDDEN.getCode(), "权限不足，禁止访问")
                            ));
                        }));

        // 返回配置好的安全过滤链
        return http.build();
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    /**
     * 配置AuthenticationManager bean
     * <p>
     * 该方法从AuthenticationConfiguration中获取AuthenticationManager
     * 主要用于Spring Security配置，以便处理认证请求
     *
     * @param config AuthenticationConfiguration实例，用于获取AuthenticationManager
     * @return 返回AuthenticationManager实例，用于处理认证逻辑
     * @throws Exception 如果获取过程中出现错误，会抛出异常
     */
    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception {
        return config.getAuthenticationManager();
    }


}
